package net.pinnoocle.playservice.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.pinnoocle.playcommon.utils.BigDecimalMathUtil;
import net.pinnoocle.playcommon.utils.HelpUtils;
import net.pinnoocle.playdao.dao.OrderDao;
import net.pinnoocle.playdao.entity.ShopStatistics;
import net.pinnoocle.playdao.entity.analysis.user.UserPercentAllVo;
import net.pinnoocle.playdao.entity.analysis.user.UserPercentVo;
import net.pinnoocle.playdao.entity.analysis.user.UserStatisticsVo;
import net.pinnoocle.playdao.entity.shopPc.homePage.NumberVo;
import net.pinnoocle.playservice.service.CommonService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author ye
 * @Description
 * @create 2021-12-01 10:47
 */
@Service("userAnalysisService")
@Slf4j
public class UserAnalysisService {

    @Autowired
    UserServiceImpl userService;
    @Autowired
    ShopStatisticsServiceImpl shopStatisticsService;
    @Autowired
    OrderServiceImpl orderService;
    @Autowired
    CommonService commonService;
    @Autowired
    OrderDao orderDao;

    /**
     * 门店用户统计
     * @param searchDate
     * @param shopId
     * @return
     */
    public UserStatisticsVo userStatistics(String searchDate,String shopId){
        UserStatisticsVo userStatisticsVo = new UserStatisticsVo();
        //今天
        String today = Objects.isNull(searchDate) ? DateUtil.today() : searchDate;
        //昨天
        DateTime yesterdayDate = DateUtil.offsetDay(DateUtil.parse(today), -1);
        //今天用户统计
        ShopStatistics shopStatisticsToday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                .eq(ShopStatistics::getDateTime, today),false);
        //昨天用户统计
        String yesterdayStr = DateUtil.format(yesterdayDate, "yyyy-MM-dd");
        ShopStatistics shopStatisticsYesterday = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                .lambda()
                .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                .eq(ShopStatistics::getDateTime, yesterdayStr),false);
        //新增用户统计
        int todayAddNum = Objects.isNull(shopStatisticsToday) ? 0 : shopStatisticsToday.getAddUserNum();
        int yesterdayAddNum = Objects.isNull(shopStatisticsYesterday) ? 0 : shopStatisticsYesterday.getAddUserNum();
        NumberVo addUserNumberVo = commonService.getNumberVo(todayAddNum, yesterdayAddNum);
        userStatisticsVo.setAddUserVo(addUserNumberVo);

        //累计用户统计
        int totalToday = userService.countUserByDate(shopId, today);
        int totalYesterday = userService.countUserByDate(shopId, yesterdayStr);
        NumberVo totalUserNumberVo = commonService.getNumberVo(totalToday, totalYesterday);
        userStatisticsVo.setGrandUserVo(totalUserNumberVo);

        //统计活跃用户
        int activeToday = orderService.countActiveUser(shopId, today + " 23:59:59");
        int activeYesterday = orderService.countActiveUser(shopId, today + " 23:59:59");
        NumberVo activeUserNumberVo = commonService.getNumberVo(activeToday, activeYesterday);
        userStatisticsVo.setActiveUserVo(activeUserNumberVo);

        //统计付费用户
        int todayPayNum = Objects.isNull(shopStatisticsToday) ? 0 : shopStatisticsToday.getPayUserNum();
        int yesterdayPayNum = Objects.isNull(shopStatisticsYesterday) ? 0 : shopStatisticsYesterday.getPayUserNum();
        NumberVo payUserNumberVo = commonService.getNumberVo(todayPayNum, yesterdayPayNum);
        userStatisticsVo.setPayUserVo(payUserNumberVo);

        //统计累计付费用户
        int totalPayToday = userService.countPayUserByDate(shopId, today);
        int totalPayYesterday = userService.countPayUserByDate(shopId, yesterdayStr);
        NumberVo totalPayNumberVo = commonService.getNumberVo(totalPayToday, totalPayYesterday);
        userStatisticsVo.setTotalPayUserVo(totalPayNumberVo);
        return userStatisticsVo;
    }

    /**
     * 本周用户趋势图
     * @param shopId
     * @return
     */
    public Map<String,List<Map<String,Integer>>> userTrendChart(String shopId){
        HashMap<String, List<Map<String,Integer>>> userTrendMap = new HashMap<>();
        List<Map<String, Integer>> addUserMap = new ArrayList<>();
        List<Map<String, Integer>> payUserMap = new ArrayList<>();
        for (int i = 1; i <=7 ; i++) {
            HashMap<String, Integer> addUserHastMap = new HashMap<>();
            HashMap<String, Integer> payUserHastMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dataStr = DateUtil.formatDate(date);
            ShopStatistics shopStatistics = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                    .lambda()
                    .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                    .eq(ShopStatistics::getDateTime, dataStr),false);
            int addUser = Objects.isNull(shopStatistics) ? 0 : shopStatistics.getAddUserNum();
            addUserHastMap.put(dataStr,addUser);
            addUserMap.add(addUserHastMap);
            int payUser = Objects.isNull(shopStatistics) ? 0 : shopStatistics.getPayUserNum();
            payUserHastMap.put(dataStr,payUser);
            payUserMap.add(payUserHastMap);
        }
        userTrendMap.put("addUser",addUserMap);
        userTrendMap.put("payUser",payUserMap);
        return userTrendMap;
    }

    /**
     * 用户转化率统计
     * @param shopId
     * @return
     */
    public UserPercentAllVo userPercent(String shopId){
        UserPercentAllVo userPercentAllVo = new UserPercentAllVo();
        //累计用户
        int totalUserNum = userService.countUserByDate(shopId, null);
        //新支付用户数
        int payNewUserNum = userService.countNewPayUserNum(shopId);
        //老支付用户数
        int payOldUserNum = userService.countOldPayUserNum(shopId);
        //全部成交用户数
        int allPayUserNum = payNewUserNum+payOldUserNum;

        //全部成交用户统计
        String totalPercent = HelpUtils.getPercent(allPayUserNum, totalUserNum);
        //总营业额
        BigDecimal totalAmount = orderDao.shopOrderStatisticsByHour(shopId, null, null, 1);
        //客单价（总营业额/累计用户数）
        double totalPerTransactionTotal = BigDecimalMathUtil.div(totalAmount.doubleValue(), totalUserNum);
        double totalPerTransaction = HelpUtils.setScaleNumber(totalPerTransactionTotal);
        UserPercentVo allUserVo = new UserPercentVo();
        allUserVo.setNumber(totalUserNum);
        allUserVo.setTotalPayPercent(totalPercent);
        allUserVo.setTotalPayPrice(totalAmount.doubleValue());
        allUserVo.setPerTransaction(totalPerTransaction);
        userPercentAllVo.setAllUser(allUserVo);

        //新付费用户统计
        String newPercent = HelpUtils.getPercent(payNewUserNum, totalUserNum);
        HashMap<String, Object> newPayMap = orderDao.calculateNewPayUser(shopId,null,null);
        BigDecimal newTotalPriceDecimal = (BigDecimal) newPayMap.get("totalPrice");
        double newTotalPrice = newTotalPriceDecimal.doubleValue();
        //客单价（总营业额/累计用户数）
        double newPerTransactionTotal = BigDecimalMathUtil.div(newTotalPrice, payNewUserNum);
        double newPerTransaction = HelpUtils.setScaleNumber(newPerTransactionTotal);
        UserPercentVo newPayUserVo = new UserPercentVo();
        newPayUserVo.setNumber(payNewUserNum);
        newPayUserVo.setTotalPayPercent(newPercent);
        newPayUserVo.setTotalPayPrice(newTotalPrice);
        newPayUserVo.setPerTransaction(newPerTransaction);
        userPercentAllVo.setNewPayUser(newPayUserVo);

        //老付费用户统计
        String oldPercent = HelpUtils.getPercent(payOldUserNum, totalUserNum);
        HashMap<String, Object> oldPayMap = orderDao.calculateOldPayUser(shopId,null,null);
        BigDecimal oldTotalPriceDecimal = (BigDecimal) oldPayMap.get("totalPrice");
        double oldTotalPrice = oldTotalPriceDecimal.doubleValue();
        //客单价（总营业额/累计用户数）
        double oldPerTransactionTotal = BigDecimalMathUtil.div(oldTotalPrice, payOldUserNum);
        double oldPerTransaction = HelpUtils.setScaleNumber(oldPerTransactionTotal);
        UserPercentVo oldPayUserVo = new UserPercentVo();
        oldPayUserVo.setNumber(payOldUserNum);
        oldPayUserVo.setTotalPayPercent(oldPercent);
        oldPayUserVo.setTotalPayPrice(oldTotalPrice);
        oldPayUserVo.setPerTransaction(oldPerTransaction);
        userPercentAllVo.setOldPayUser(oldPayUserVo);
        return userPercentAllVo;
    }

    /**
     * 新老用户数趋势图
     * @param shopId
     * @return
     */
    public Map<String,List<Map<String,Integer>>> userNumberChart(String shopId){
        HashMap<String, List<Map<String,Integer>>> userTrendMap = new HashMap<>();
        List<Map<String, Integer>> newUserMap = new ArrayList<>();
        List<Map<String, Integer>> oldUserMap = new ArrayList<>();
        for (int i = 1; i <=7 ; i++) {
            HashMap<String, Integer> newUserHastMap = new HashMap<>();
            HashMap<String, Integer> oldUserHastMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dataStr = DateUtil.formatDate(date);
            ShopStatistics shopStatistics = shopStatisticsService.getOne(new QueryWrapper<ShopStatistics>()
                    .lambda()
                    .eq(StringUtils.isNotBlank(shopId),ShopStatistics::getShopId, shopId)
                    .eq(ShopStatistics::getDateTime, dataStr),false);
            int newPayUser = Objects.isNull(shopStatistics) ? 0 : shopStatistics.getPayUserNum();
            newUserHastMap.put(dataStr,newPayUser);
            newUserMap.add(newUserHastMap);
            int oldPayUser = Objects.isNull(shopStatistics) ? 0 : shopStatistics.getOldPayUserNum();
            oldUserHastMap.put(dataStr,oldPayUser);
            oldUserMap.add(oldUserHastMap);
        }
        userTrendMap.put("newNumberChart",newUserMap);
        userTrendMap.put("oldNumberChart",oldUserMap);
        return userTrendMap;
    }

    /**
     * 新老用户客单价趋势图
     * @param shopId
     * @return
     */
    public Map<String,List<Map<String,Double>>> userPreTransaction(String shopId){
        HashMap<String, List<Map<String,Double>>> userTrendMap = new HashMap<>();
        List<Map<String, Double>> newUserMap = new ArrayList<>();
        List<Map<String, Double>> oldUserMap = new ArrayList<>();
        for (int i = 1; i <=7 ; i++) {
            HashMap<String, Double> newUserHastMap = new HashMap<>();
            HashMap<String, Double> oldUserHastMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dataStr = DateUtil.formatDate(date);
            String startDate = dataStr + " 00:00:00";
            String endDate = dataStr + " 23:59:59";
            //新用户客单价
            HashMap<String, Object> newPayPriceAndNumber = orderDao.calculateNewPayUser(shopId, startDate, endDate);
            BigDecimal newPayUserNum = (BigDecimal) newPayPriceAndNumber.get("total");
            BigDecimal newTotalPrice = (BigDecimal) newPayPriceAndNumber.get("totalPrice");
            double preTransactionNew = HelpUtils.getPreTransaction(newTotalPrice.doubleValue(),newPayUserNum.intValue());
            newUserHastMap.put(dataStr,preTransactionNew);
            newUserMap.add(newUserHastMap);

            //老用户客单价
            HashMap<String, Object> oldPayPriceAndNumber = orderDao.calculateOldPayUser(shopId, startDate, endDate);
            BigDecimal oldPayUserNum = (BigDecimal) oldPayPriceAndNumber.get("total");
            BigDecimal oldTotalPrice = (BigDecimal) oldPayPriceAndNumber.get("totalPrice");
            double preTransactionOld = HelpUtils.getPreTransaction(oldTotalPrice.doubleValue(),oldPayUserNum.intValue());
            oldUserHastMap.put(dataStr,preTransactionOld);
            oldUserMap.add(oldUserHastMap);
        }
        userTrendMap.put("newPreTransaction",newUserMap);
        userTrendMap.put("oldPreTransaction",oldUserMap);
        return userTrendMap;
    }

    /**
     * 本周新老用户支付金额趋势图
     * @param shopId
     * @return
     */
    public Map<String,List<Map<String,Double>>> userPayPrice(String shopId){
        HashMap<String, List<Map<String,Double>>> userTrendMap = new HashMap<>();
        List<Map<String, Double>> newUserMap = new ArrayList<>();
        List<Map<String, Double>> oldUserMap = new ArrayList<>();
        for (int i = 1; i <=7 ; i++) {
            HashMap<String, Double> newUserHastMap = new HashMap<>();
            HashMap<String, Double> oldUserHastMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dataStr = DateUtil.formatDate(date);
            String startDate = dataStr + " 00:00:00";
            String endDate = dataStr + " 23:59:59";
            //新用户客单价
            HashMap<String, Object> newPayPriceAndNumber = orderDao.calculateNewPayUser(shopId, startDate, endDate);
            BigDecimal newTotalPrice = (BigDecimal) newPayPriceAndNumber.get("totalPrice");
            newUserHastMap.put(dataStr,newTotalPrice.doubleValue());
            newUserMap.add(newUserHastMap);

            //老用户客单价
            HashMap<String, Object> oldPayPriceAndNumber = orderDao.calculateOldPayUser(shopId, startDate, endDate);
            BigDecimal oldTotalPrice = (BigDecimal) oldPayPriceAndNumber.get("totalPrice");
            oldUserHastMap.put(dataStr,oldTotalPrice.doubleValue());
            oldUserMap.add(oldUserHastMap);
        }
        userTrendMap.put("newPriceUser",newUserMap);
        userTrendMap.put("oldPriceUser",oldUserMap);
        return userTrendMap;
    }

    /**
     * 新老用户支付转化率趋势图
     * @return
     */
    public Map<String,List<Map<String,Double>>> userPayPercent(String shopId) {
        //累计用户
        int totalUserNum = userService.countUserByDate(shopId, null);
        HashMap<String, List<Map<String,Double>>> userTrendMap = new HashMap<>();
        List<Map<String, Double>> newUserMap = new ArrayList<>();
        List<Map<String, Double>> oldUserMap = new ArrayList<>();
        for (int i = 1; i <=7 ; i++) {
            HashMap<String, Double> newUserHastMap = new HashMap<>();
            HashMap<String, Double> oldUserHastMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dataStr = DateUtil.formatDate(date);
            String startDate = dataStr + " 00:00:00";
            String endDate = dataStr + " 23:59:59";
            //新用户转化率
            HashMap<String, Object> newPayPriceAndNumber = orderDao.calculateNewPayUser(shopId, startDate, endDate);
            BigDecimal newPayUserNum = (BigDecimal) newPayPriceAndNumber.get("total");
            double percentNoCentNew = HelpUtils.getPercentNoCent(newPayUserNum.intValue(), totalUserNum);
            newUserHastMap.put(dataStr,percentNoCentNew);
            newUserMap.add(newUserHastMap);
            //老用户转化率
            HashMap<String, Object> oldPayPriceAndNumber = orderDao.calculateOldPayUser(shopId, startDate, endDate);
            BigDecimal oldPayUserNum = (BigDecimal) oldPayPriceAndNumber.get("total");
            double percentNoCentOld = HelpUtils.getPercentNoCent(oldPayUserNum.intValue(), totalUserNum);
            oldUserHastMap.put(dataStr,percentNoCentOld);
            oldUserMap.add(oldUserHastMap);
        }
        userTrendMap.put("newPayPercent",newUserMap);
        userTrendMap.put("oldPayPercent",oldUserMap);
        return userTrendMap;
    }

    /**
     * 复购率
     * @param type
     * @param shopId
     * @return
     */
    public List<Map<String,Double>> secondPayTendencyChart(Integer type,String shopId){
        int startNum = (type == 0 ) ? 7 : 30;
        List<Map<String, Double>> mapList = new ArrayList<>();
        for (int i = 1; i <=startNum ; i++) {
            HashMap<String, Double> stringIntegerHashMap = new HashMap<>();
            String today = DateUtil.today();
            DateTime date = DateUtil.offsetDay(DateUtil.parse(today), -i);
            String dateStr = DateUtil.formatDate(date);
            String startDate = dateStr + " 00:00:00";
            String endDate = dateStr + " 23:59:59";
            int todayAllUserNum = orderDao.countTodayAllUser(shopId, startDate, endDate);
            int todaySecondPayUserNum = orderDao.countTodaySecondPayUser(shopId, startDate, endDate);
            double percentNoCent = HelpUtils.getPercentNoCent(todaySecondPayUserNum, todayAllUserNum);
            stringIntegerHashMap.put(dateStr,percentNoCent);
            mapList.add(stringIntegerHashMap);
        }
        return mapList;
    }
}
